package com.guigu.gulicommon.annotations.impl;

import com.guigu.gulicommon.annotations.CheckEnumParam;
import com.guigu.gulicommon.api.BaseDataEnum;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 校验枚举参数是否在给定的枚举类中
 *
 * @author 陈俊杰
 * @version 1.0
 * @since 2024/8/15 20:58
 */
public class CheckEnumParamImpl implements ConstraintValidator<CheckEnumParam, Object> {

    // 定义一个泛型类变量，用于存储枚举类型
    private Class<? extends Enum<?>> enumClass;
    // 定义一个字符串变量，用于存储验证失败时的错误信息
    private String message;
    // 定义一个字符串变量，用于存储标识符
    private String tag;

    /**
     * 初始化方法，用于从注解中获取枚举类型、错误信息和标识符
     *
     * @param constraintAnnotation 从CheckEnumParam注解中获取配置信息
     */
    @Override
    public void initialize(CheckEnumParam constraintAnnotation) {
        this.enumClass = constraintAnnotation.enumClass();
        this.message = constraintAnnotation.message();
        this.tag = constraintAnnotation.tag();
    }

    /**
     * 验证方法，用于检查给定的值是否为指定枚举类型的有效值
     *
     * @param value   待验证的值
     * @param context 验证上下文
     * @return 如果值有效返回true，否则返回false
     */
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        // 构建错误消息
        String enumDescriptions = Stream.of(enumClass.getEnumConstants())
                .filter(e -> e instanceof BaseDataEnum)
                .map(e -> ((BaseDataEnum) e).getName())
                .collect(Collectors.joining(", "));

        // 禁用默认的约束违规，以便自定义错误消息
        context.disableDefaultConstraintViolation();
        // 自定义错误消息模板
        context.buildConstraintViolationWithTemplate(
                        message.replace("{tag}", tag)
                                .replace("{enumDescriptions}", enumDescriptions))
                .addConstraintViolation();

        // 如果值为空，则视为无效
//        if (value == null) {
//            return false;
//        }
        // 验证值是否为枚举类的有效值
        if (value instanceof BaseDataEnum) {
            BaseDataEnum baseDataEnum = (BaseDataEnum) value;
            // 检查值是否在枚举常量列表中
            return Arrays.asList(enumClass.getEnumConstants()).contains(baseDataEnum);
        }
        return false;
    }
}
